package net.alche.sdd.servlet.imp;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.logging.FileHandler;
import java.util.logging.LogManager;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.jul.JDK14LoggerAdapter;
import org.smartboot.http.server.HttpBootstrap;
import org.smartboot.http.server.HttpRequest;
import org.smartboot.http.server.HttpResponse;
import org.smartboot.http.server.HttpServerHandler;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException;
import net.alche.al.util.AC;
import net.alche.al.util.Far;
import net.alche.al.util.M;
import net.alche.sdd.servlet.SddHttpServer;
import net.alche.sdd.servlet.SddServletDispatch;
import net.alche.sdd.servlet.biz.SddApplicatonBiz;

public class SddHttpServerHot {
  public static final Logger logger = LoggerFactory.getLogger(SddHttpServerBase.class);
  int port = 8080;
  String[] packages = null;
  public boolean isBaseDispath = false;
  // SddServletDispatchBase dispatchBase = null;
  SddServletDispatchHot dispatch = null;
  SddApplicatonBiz appBiz = new SddApplicatonBiz();
  HttpBootstrap boot = null;
  boolean isHot = true;

  public SddHttpServerHot(int port, String[] packages) {
    this.port = port;
    this.packages = packages;
    dispatch = new SddServletDispatchHot(appBiz);
    // dispatch = new SddServletDispatchBase(appBiz);
  }

  public void start() {
    initLogger();
    startServer();
    if (AC.system.isRunJar()) {
      if (FileUtil.exist("./ser/logs")) {
        FileUtil.mkdir("./ser/logs");
      }
    }
    // startTest();
  }

  public void startServer() {
    appBiz.setConf(initConf());
    String scanPackage = appBiz.getStr("servlet.scanPackage");
    if (!AC.empty(scanPackage)) {
      packages = scanPackage.split(",");
    }
    if (port == 0) {
      port = appBiz.getInt("servlet.port");
    }
    boot = new HttpBootstrap();
    boot.configuration().debug(false);
    // boot.configuration().writeMemoryPool(1024 * 100, 10);
    boot.httpHandler(new HttpServerHandler() {
      @Override
      public void handle(HttpRequest request, HttpResponse response) throws IOException {
        SddHttpRequestResp res = new SddHttpRequestResp(request, response);
        if (dispatch.appNamePath != null) {
          res.appPath = dispatch.appNamePath;
        }
        dispatch.dispatch(res.getHttpType(), request.getRequestURI(), res);
      }
    });
    boot.setPort(port).start();
    logger.info("sdd-server starting ....");
    logger.info("load jdbc...");
    appBiz.initSddFatis();
    dispatch.setBean("SddApplicatonBiz", appBiz);
    dispatch.init();
    dispatch.loadBean(packages);
    dispatch.serverStartSuccess();
    logger.info("sdd-server boot success! port = [" + port + "]");
  }

  public Map<String, String> initConf() {
    String json = AC.file.readClassRes("conf/application.json");
    Map<String, String> mpConf = new HashMap<>();
    Map mp = Far.tl.fromJsonMap(json);
    recurConf(mpConf, mp, null);
    return mpConf;
  }

  void initLogger() {
    try {
      LogManager.getLogManager()
          .readConfiguration(AC.system.getClassPathRes("conf/logging.properties"));
    } catch (Exception e) {
      e.printStackTrace();
    }
    // log4j2
    // Configurator.initialize("Log4j2", "classpath:conf/log4j2.xml");
  }

  public void recurConf(Map<String, String> mpConf, Map par, String parPath) {
    Set<String> keys = par.keySet();
    if (parPath == null) {
      parPath = "";
    } else {
      parPath += ".";
    }
    for (String key : keys) {
      Object obj = par.get(key);
      if (obj == null)
        continue;
      if (obj instanceof Map) {
        recurConf(mpConf, (Map) obj, parPath + key);
      } else {
        mpConf.put(parPath + key, obj.toString());
      }
    }
  }
}
